#pragma once

#include "vector2d.h"
#include "dll_setup.h"

template <typename T>
class SAPPHIRE_ENGINE Rect
{
public:
	Rect() : 
		position(Vector2d<T>()),size(Vector2d<T>())
	{}

	Rect(const Vector2d<T>& pos,const Vector2d<T>& siz) : 
		position(pos), 
		size(siz)	
	{}

	Rect(T XPos,T YPos,T XSize,T YSize) : 
		position(Vector2d<T>(XPos,YPos)), 
		size(Vector2d<T>(XSize,YSize)) 
	{}

	Rect(const Rect<T> &rect) : 
		position(rect.position), 
		size(rect.size)
	{}

	~Rect<T>(){}

	inline Rect<T>& operator=(const Rect<T>& sourceRect)
	{
		if (this!=&sourceRect)
		{
			position=sourceRect.position;
			size=sourceRect.size;
		}
		return *this;
	}

	inline bool operator==(const Rect<T>& sourceRect) const
	{
		return position==sourceRect.position && size==sourceRect.size;
	}

	inline bool operator!=(const Rect<T>& sourceRect) const
	{
		return position!=sourceRect.position || size!=sourceRect.size;
	}

	inline Rect<T> operator + (const Rect<T> &other) const
	{
		return Rect<T>(position+other.position,size+other.GetSize);
	}

	inline Rect<T>& operator += (const Rect<T> &other)
	{
		position += other.position;
		size += other.size;
		return *this;
	}

	inline Rect<T> operator - (const Rect<T> &other) const
	{
		return Rect<T>(position-other.position,size-other.GetSize);
	}

	inline Rect<T>& operator -= (const Rect<T> &other)
	{
		position -= other.position;
		size -= other.size;
		return *this;
	}

	inline Rect<T> operator / (const Rect<T> &other) const
	{
		return Rect<T>(position/other.position,size/other.GetSize);
	}

	inline Rect<T>& operator /= (const Rect<T> &other)
	{
		position /= other.position;
		size /= other.size;
		return *this;
	}

	inline Rect<T> operator * (const Rect<T> &other) const
	{
		return Rect<T>(position*other.position,size*other.GetSize);
	}

	inline Rect<T>& operator *= (const Rect<T> &other)
	{
		position *= other.position;
		size *= other.size;
		return *this;
	}

	inline Rect<T> operator - () const
	{
		return Rect<T>(-position, -size);
	}

	inline Vector2d<T> GetCenter() const
	{
		return Vector2d<T>(position.x + size.x/2, position.y + size.y/2);
	}

	inline void GetCenter(T &nx, T &ny) const
	{
		nx = position.x + size.x/2;
		ny = position.y + size.y/2;
	}

	T GetXCenter()
	{
		return position.x+(size.x/2);
	}

	T GetYCenter()
	{
		return position.y+(size.y/2);
	}

	void SetCenter(Vector2d<T> pos)
	{
		T xs=size.x;
		T ys=size.y;

		Vector2d<T> newPosition=Vector2d<T>(pos.x-(xs/2),pos.y-(ys/2));

		position=newPosition;
	}

	inline bool isEmpty() const
	{
		return position.IsNull() == size.IsNull() == true;
	}
	

	bool IsPointOver(Vector2d<T> point)
	{
		bool res=false;

		T px=point.x;
		T py=point.y;

		T rpx=position.x;
		T rpy=position.y;

		T rxs=size.x;
		T rys=size.y;

		if ((px>=rpx) && (py>=rpy) && (px<rpx+rxs) && (py<rpy+rys)) res=true;

		return res;
	}

	void SetPosition(Vector2d<T> pos)
	{
		position=pos;
	}

	void SetSize(Vector2d<T> nsize)
	{
		size=nsize;
	}

	Vector2d<T> position;
	Vector2d<T> size;
};

typedef Rect<signed int> Recti;
typedef Rect<float> Rectf;